package controllers

import (
	"bytes"
	"context"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/minio/minio-go/v7"
	ffmpeg "github.com/u2takey/ffmpeg-go"
	"image"
	"image/jpeg"
	"my-gin-tiktok/common/response"
	"my-gin-tiktok/global"
	"my-gin-tiktok/utils"
	"os"
)

// ReadFrameAsJpeg 从视频流中截取一帧并返回 需要在本地环境中安装ffmpeg并将bin添加到环境变量
func readFrameAsJpeg(filePath string) ([]byte, error) {
	reader := bytes.NewBuffer(nil)
	err := ffmpeg.Input(filePath).Filter("select", ffmpeg.Args{fmt.Sprintf("gte(n,%d)", 1)}).
		Output("pipe:", ffmpeg.KwArgs{"vframes": 1, "format": "image2", "vcodec": "mjpeg"}).
		WithOutput(reader, os.Stdout).Run()
	if err != nil {
		return nil, err
	}
	img, _, err := image.Decode(reader)
	if err != nil {
		return nil, err
	}
	buf := new(bytes.Buffer)
	_ = jpeg.Encode(buf, img, nil)
	return buf.Bytes(), err
}

func UploadImage(ctx *gin.Context) {
	file, err := ctx.FormFile("file")
	if err != nil {
		response.ValidateFail(ctx, err.Error())
		return
	}

	src, err := file.Open()
	if err != nil {
		response.BusinessFail(ctx, err.Error())
		return
	}
	defer src.Close()

	urlStart := "http://"
	if global.App.Config.OSS.SSL {
		urlStart = "https://"
	}

	filename := utils.Flake.NewSnowFlake()
	imageName := filename + ".jpeg"
	_, err = global.App.Oss.PutObject(context.Background(), global.App.Config.OSS.ImageBucketName, imageName, src, file.Size, minio.PutObjectOptions{ContentType: "image/jpeg"})
	imageURL := fmt.Sprintf("%s%s/%s/%s", urlStart, global.App.Config.OSS.EndPoint, global.App.Config.OSS.ImageBucketName, imageName)

	data := make(map[string]string, 1)
	data["image_url"] = imageURL
	response.Success(ctx, data)
}

func UploadVideo(ctx *gin.Context) {
	file, err := ctx.FormFile("file")
	if err != nil {
		response.ValidateFail(ctx, err.Error())
		return
	}

	src, err := file.Open()
	if err != nil {
		response.BusinessFail(ctx, err.Error())
		return
	}
	defer src.Close()

	urlStart := "http://"
	if global.App.Config.OSS.SSL {
		urlStart = "https://"
	}

	// 上传文件到 MinIO
	filename := utils.Flake.NewSnowFlake()
	videoName := filename + ".mp4"
	_, err = global.App.Oss.PutObject(context.Background(), global.App.Config.OSS.VideoBucketName, videoName, src, file.Size, minio.PutObjectOptions{})
	if err != nil {
		response.BusinessFail(ctx, err.Error())
		return
	}
	videoURL := fmt.Sprintf("%s%s/%s/%s", urlStart, global.App.Config.OSS.EndPoint, global.App.Config.OSS.VideoBucketName, videoName)

	// 获取封面
	coverData, _ := readFrameAsJpeg(videoURL)
	imageName := filename + ".jpeg"
	coverReader := bytes.NewReader(coverData)
	_, err = global.App.Oss.PutObject(context.Background(), global.App.Config.OSS.ImageBucketName, imageName, coverReader, coverReader.Size(), minio.PutObjectOptions{ContentType: "image/jpeg"})
	if err != nil {
		response.BusinessFail(ctx, err.Error())
		return
	}

	imageURL := fmt.Sprintf("%s%s/%s/%s", urlStart, global.App.Config.OSS.EndPoint, global.App.Config.OSS.ImageBucketName, imageName)
	data := map[string]string{}
	data["video_url"] = videoURL
	data["image_url"] = imageURL
	response.Success(ctx, data)
}
